/*
 * All rights Reserved, Designed By cloudland Copyright(C) 2010-2014
 *
 * fileName:  PictureDispose.java
 * author:  lei
 * Company:  Cloudland Studio
 * Createdate:  2013-9-15 上午11:17:31
 *   
 * Modification  History:
 *     Date           Author        Version        
 * -------------------------------------------
 * 2013-9-15          Lei            1.0        
 *
 * Why & What is modified:
 * 1.0: 文件创建
 */
package org.cloudland.picture;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.imageio.ImageIO;

import org.cloudland.context.exception.ConstantsException;
import org.cloudland.context.exception.ContextException;

import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;


 /**
 * <pre> 
 * 图片处理方式。
 * </pre>
 * @ClassName  PictureDispose
 * @author  lei
 * @version  %I%, %G%
 * @see  
 * @since   JDK1.6
 *
 */
@SuppressWarnings("restriction")
public class PictureDispose {
	
	/**
	 * <pre>
	 * 压缩图片至指定大小。水印接口可以为空，为空情况下，图片不添加水印。
	 * </pre>
	 *
	 * @param resFile 原图片
	 * @param destFile 存放图片的目标文件
	 * @param width 压缩宽
	 * @param height 压缩高
	 * @param sign 水印接口  
	 */
	public static void reduction(File resFile, File destFile, int width, int height, IPictureSign sign)
    {
        
        InputStream in = null;
        ByteArrayOutputStream byteOut = null;
        try
        {
            in = new FileInputStream(resFile);
            byteOut = reduction(in, width, height, sign);
        }
        catch (FileNotFoundException e)
        {
            // 图片剪裁操作时，读取原图错误，该文件不存在。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0001, e);
        }
        catch (ContextException e)
        {
            // 将底层封装好的异常外抛
            throw e;
        }
        finally
        {
            if (null != in)
            {
                try
                {
                    // 关闭文件读入流
                    in.close();
                }
                catch (IOException e)
                {
                    // 图片剪裁操作时，不能正确的完成关闭读取流或写入流。
                    throw new ContextException(ConstantsException.CONTEXT_PICTURE_0002, e);
                }
            }
        }
        
        // 输出到目标文件
        OutputStream out = null;
        try
        {
            out = new FileOutputStream(destFile);
            byteOut.writeTo(out);
        }
        catch (FileNotFoundException e)
        {
            // 图片剪裁操作时，将完成的图片写入文件时出错，目标文件不存在。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0003, e);
        }
        catch (IOException e)
        {
            // 图片剪裁操作时，拷贝源输入流到目标流失败。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0004, e);
        }
        finally
        {
            if (null != out)
            {
                try
                {
                    out.close();
                }
                catch (IOException e)
                {
                    // 图片剪裁操作时，不能正确关闭目标文件的写入流。
                    throw new ContextException(ConstantsException.CONTEXT_PICTURE_0002, e);
                }
            }
        }
    }
		

	/**
	 * <pre>
	 * 压缩图片至指定大小。水印接口可以为空，为空情况下，图片不添加水印。
	 * </pre>
	 *
	 * @param input 原图片文件流
	 * @param width 压缩宽
	 * @param height 压缩高
	 * @param sign 水印操作接口
	 * @return 图片处理结束，输出流对象  
	 */
	public static ByteArrayOutputStream reduction(InputStream input, int width, int height, IPictureSign sign)
    {
        
        BufferedImage img = null;
        try
        {
            img = ImageIO.read(input);
        }
        catch (IOException e)
        {
            // 读取图片失败，不能正确获取图片信息。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0005, e);
        }
        
        // 定义画布尺寸
        int canvasWidth = width, canvasHeight = height;// 画布尺寸就等于目标尺寸
        //int canvasWidth = 1024, canvasHeight = 768;
        
        // 定义新画布
        BufferedImage canvas = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.SCALE_SMOOTH);
        // 将原图按指定宽度、高度在新画布上绘制。绘制位置起点坐标 x:0 y:0
        Graphics g = canvas.getGraphics();
        //g.setColor(new Color(33, 99, 00));// 填充画布空白处颜色, 现在暂无使用
        g.fillRect(0, 0, canvasWidth, canvasHeight);
        g.drawImage(img.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH), 0, 0, null);
        
        // 添加水印
        if (null != sign)
        {
            try
            {
                sign.doSign(canvas.createGraphics(), canvasWidth, canvasHeight);
            }
            catch (Exception e)
            {
                // 判断此异常是否已经被封装
                if (e instanceof ContextException)
                {
                    throw (ContextException) e;
                }
                // 给图片添加水印失败。
                throw new ContextException(ConstantsException.CONTEXT_PICTURE_0006, e);
            }
        }
        
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(output);
        try
        {
            encoder.encode(canvas);
        }
        catch (ImageFormatException e)
        {
            // 图片转换失败，不能够将该图片转为指定图片类型。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0007, e);
        }
        catch (IOException e)
        {
            // 图片转换过程中，读取或写入信息失败。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0008, e);
        }
        
        return output;
    }
	
	/**
	 * <pre>
	 * 切割图片。
	 * </pre>
	 *
	 * @param input 图片文件流
	 * @param width 生成图片宽
	 * @param height 生成图片高
	 * @param beginX 在原图上切割起始点X坐标
	 * @param beginY 在原图上切割起始点Y坐标
	 * @param endX 在原图上切割结束点X坐标
	 * @param endY 在原图上切割结束点Y坐标
	 * @param sign 水印操作接口
	 * @return 图片处理结束，输出流对象
	 */
	public static ByteArrayOutputStream cut(InputStream input, int width, int height, int beginX, int beginY, int endX, int endY, IPictureSign sign) {
        BufferedImage img = null;
        try
        {
            img = ImageIO.read(input);
        }
        catch (IOException e)
        {
            // 读取图片失败，不能正确获取图片信息。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0005, e);
        }
        
        // 定义画布尺寸
        int canvasWidth = width, canvasHeight = height;// 画布尺寸就等于目标尺寸
        //int canvasWidth = 1024, canvasHeight = 768;
        
        // 定义新画布
        BufferedImage canvas = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.SCALE_SMOOTH);
        // 将原图按指定宽度、高度在新画布上绘制。绘制位置起点坐标 x:0 y:0
        Graphics g = canvas.getGraphics();
        //g.setColor(new Color(33, 99, 00));// 填充画布空白处颜色, 现在暂无使用
        g.fillRect(0, 0, canvasWidth, canvasHeight);
        g.drawImage(img, 0, 0, canvasWidth, canvasHeight, beginX, beginY, endX, endY, null);
        
        // 添加水印
        if (null != sign)
        {
            try
            {
                sign.doSign(canvas.createGraphics(), canvasWidth, canvasHeight);
            }
            catch (Exception e)
            {
                // 判断此异常是否已经被封装
                if (e instanceof ContextException)
                {
                    throw (ContextException) e;
                }
                // 给图片添加水印失败。
                throw new ContextException(ConstantsException.CONTEXT_PICTURE_0006, e);
            }
        }
        
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(output);
        try
        {
            encoder.encode(canvas);
        }
        catch (ImageFormatException e)
        {
            // 图片转换失败，不能够将该图片转为指定图片类型。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0007, e);
        }
        catch (IOException e)
        {
            // TODO 图片转换过程中，读取或写入信息失败。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0008, e);
        }
        
        return output;
    }
	
	/**
	 * <pre>
	 * 切割图片。
	 * </pre>
	 *
	 * @param resFile 引用的图片文件
	 * @param destFile 生成图片存放位置
	 * @param width 生成图片宽
	 * @param height 生成图片高
	 * @param beginX 在原图上切割起始点X坐标
	 * @param beginY 在原图上切割起始点Y坐标
	 * @param endX 在原图上切割结束点X坐标
	 * @param endY 在原图上切割结束点Y坐标
	 * @param sign 水印操作接口
	 */
	public static void cut(File resFile, File destFile, int width, int height, int beginX, int beginY, int endX, int endY, IPictureSign sign)
    {
        
        InputStream in = null;
        ByteArrayOutputStream byteOut = null;
        try
        {
            in = new FileInputStream(resFile);
            byteOut = cut(in, width, height, beginX, beginY, endX, endY, sign);
        }
        catch (FileNotFoundException e)
        {
            // 图片剪裁操作时，读取原图错误，该文件不存在。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0001, e);
        }
        catch (ContextException e)
        {
            // 将底层封装好的异常外抛
            throw e;
        }
        finally
        {
            if (null != in)
            {
                try
                {
                    // 关闭文件读入流
                    in.close();
                }
                catch (IOException e)
                {
                    // 图片剪裁操作时，不能正确的完成关闭读取流或写入流。
                    throw new ContextException(ConstantsException.CONTEXT_PICTURE_0002, e);
                }
            }
        }
        
        // 输出到目标文件
        OutputStream out = null;
        try
        {
            out = new FileOutputStream(destFile);
            byteOut.writeTo(out);
        }
        catch (FileNotFoundException e)
        {
            // 图片剪裁操作时，将完成的图片写入文件时出错，目标文件不存在。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0003, e);
        }
        catch (IOException e)
        {
            // 图片剪裁操作时，拷贝源输入流到目标流失败。
            throw new ContextException(ConstantsException.CONTEXT_PICTURE_0004, e);
        }
        finally
        {
            if (null != out)
            {
                try
                {
                    out.close();
                }
                catch (IOException e)
                {
                    // 图片剪裁操作时，不能正确关闭目标文件的写入流。
                    throw new ContextException(ConstantsException.CONTEXT_PICTURE_0002, e);
                }
            }
        }
    }
	
}
	
